﻿using System;
using System.Collections;
using UnityEngine;

namespace Whoot
{
    public enum TaskStatus
    {
        None = 0,
        Running,
        Success,
        Failure
    }

    public abstract class Task
    {
        protected string Err = string.Empty;
        public virtual float Progress { get; protected set; }

        public virtual string ErrInfo => Err;

        private bool _latch;

        //protected object mOwnerSystem;
        private float _startedTime;

        /// <summary>
        /// 扩展参数
        /// </summary>
        public object ExtendArgs;

        public Task SetExtend(object args)
        {
            ExtendArgs = args;
            return this;
        }

        public TaskStatus TaskStatus { get; private set; }


        public bool IsRunning => TaskStatus == TaskStatus.Running;

        public Action<bool> OnFinished = null;

        public void Execute(Action<bool> callback = null)
        {
            if (callback != null) OnFinished = callback;
            Progress = 0;
            if (!IsRunning) MonoManager.Inst.StartCoroutine(Updater());
        }

        public IEnumerator Updater()
        {
            while (Tick() == TaskStatus.Running) yield return null;

            OnFinished?.Invoke(TaskStatus == TaskStatus.Success);
        }


        internal TaskStatus Tick()
        {
            if (TaskStatus == TaskStatus.Running)
            {
                OnUpdate();
                _latch = false;
                return TaskStatus;
            }

            //如果任务结束了跳过这一帧//
            if (_latch)
            {
                _latch = false;
                return TaskStatus;
            }

            _startedTime = Time.time;
            TaskStatus = TaskStatus.Running;
            //mOwnerSystem = owner;
            OnExecute();
            if (TaskStatus == TaskStatus.Running)
                OnUpdate();
            return TaskStatus;
        }

        public void EndTask(bool success = true)
        {
            if (TaskStatus != TaskStatus.Running)
            {
                OnForcedStop();
                return;
            }

            _latch = true;
            TaskStatus = success ? TaskStatus.Success : TaskStatus.Failure;
            Progress = TaskStatus == TaskStatus.Success ? 1 : 0;
            OnStop();
        }

        public void Reset()
        {
            TaskStatus = TaskStatus.None;
            OnReset();
        }

        protected virtual void OnExecute()
        {
        }

        protected virtual void OnUpdate()
        {
        }

        protected virtual void OnStop()
        {
        }

        protected virtual void OnReset()
        {
        }

        protected virtual void OnForcedStop()
        {
        }
    }
}